const fs = require("fs");
const path = require("path");
const Koa = require("koa");
const koaStatic = require("koa-static");
const cookie = require("koa-cookie").default;
const mount = require("koa-mount");
const LRU = require("lru-cache");
const morgan = require("koa-morgan");
const logger = require("koa-logger")
const serve = require("koa-static")
const koaRouter = require("koa-router")
const koaBodyparser = require("koa-bodyparser")
const { createBundleRenderer } = require("vue-server-renderer")

const { convertMetaDataToHead } = require('./meta.js');

const isDev = process.env.NODE_ENV === "dev";
console.log('isDev ', isDev)

const isProd = process.env.NODE_ENV === 'production'
const app = new Koa()
const router = koaRouter()
const resolve = file => path.resolve(__dirname, file)

//开放dist目录
app.use(mount("/assets", koaStatic(resolve("../client/assets"))));
app.use(mount("/", koaStatic(resolve("../client/assets"))));

app.use(morgan("combined"));
app.use(cookie());

function createRenderer(bundle, options) {
  // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
  return createBundleRenderer(bundle, Object.assign(options, {
    // for component caching
    cache: new LRU({
      max: 1000,
      maxAge: 1000 * 60 * 15
    }),
    // this is only needed when vue-server-renderer is npm-linked
    // basedir: resolve('./dist'),
    // recommended for performance
    runInNewContext: false
  }))
}


let renderer
const templatePath = resolve('./index.template.html')

let port = process.env.PORT || process.env.port || 8093

// if (isProd) {
const template = fs.readFileSync(templatePath, 'utf-8')
const bundle = require('../client/vue-ssr-server-bundle.json')
const clientManifest = require('../client/vue-ssr-client-manifest.json')
renderer = createRenderer(bundle, {
  template,
  clientManifest
})
app.use(serve(path.resolve('dist/client'), {
  hidden: 'index.html'
}))


app.use(koaBodyparser())
  // app.use(json())
app.use(logger())

app.use(async function(ctx, next) {
  let start = new Date()
  await next()
  let ms = new Date() - start
  console.log('%s %s - %s', ctx.method, ctx.url, ms)
})


app.on('error', function(err, ctx) {
  console.log('server error', err)
})

// app.use(router.routes()) // 将路由规则挂载到Koa上。
// app.use(historyApiFallback())
// app.use(serve(path.resolve('dist'))) // 将webpack打包好的项目目录作为Koa静态文件服务的目录

router.get('*', async(ctx, next) => {
  return render(ctx, next)
})

const render = async(ctx, next) => {
  if (!renderer) {
    ctx.body = 'waiting for compilation... refresh in a moment.'
    return ctx.body
  } else {
    let req = ctx.req
      // ctx.type = 'html'
    ctx.set("Content-Type", "text/html");
    const s = Date.now()
    let context = {
      cookies: ctx.cookie || {},
      url: req.url,
      ...convertMetaDataToHead(ctx.path)
    }
    ctx.body = await renderToStringPromise(context, s)
    return ctx.body
  }
}

function renderToStringPromise(context, s) {
  return new Promise((resolve, reject) => {
    renderer.renderToString(context, (err, html) => {
      if (!isProd) {
        console.log(`whole request: ${Date.now() - s}ms`)
      }
      if (err) {
        console.log(err)
        resolve(err)
      } else {
        resolve(html)
      }
    })
  })
}

app.use(router.routes()) // 将路由规则挂载到Koa上。
app.use(router.allowedMethods())

module.exports = app.listen(port, () => {
  console.log(`Koa is listening in ${port}`)
})